package com.sync.utils.project.demo.controller;

import com.google.common.collect.Lists;
import com.sync.utils.common.base.controller.impl.BaseControllerImpl;
import com.sync.utils.framework.result.R;
import com.sync.utils.project.demo.pojo.AsyncData;
import com.sync.utils.project.demo.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * TODO
 *
 * @Author YWF
 * @Date 2022/2/24 17:32
 */
@RestController
public class AyncDataController extends BaseControllerImpl {

    @Autowired
    private AsyncService asyncService;

    /**
     * 用起始时间作为流的源头，按照每次加一天的方式创建一个无限流
     * @param start
     * @param end
     * @return
     */
    @GetMapping(value = "getApiDataList")
    public R getApiDataList(@RequestParam("start") String start,
                            @RequestParam("end") String end) {
        Date beginTime = new Date();
        Map<String,Object> rs = new HashMap<>();
        LocalDate timeStart = LocalDate.parse(start);
        LocalDate timeEnd = LocalDate.parse(end);
        List<String> dateList = collectLocalDates(timeStart,timeEnd);

        List<AsyncData> asyncDataList = this.getSyncData(dateList);
        //测试每100条数据插入开一个线程
        List<List<AsyncData>> lists = this.splitList(asyncDataList, 10);
        CountDownLatch countDownLatch = new CountDownLatch(lists.size());

        int count =0;
        for (List<AsyncData> listSub:lists) {
            asyncService.executeAsync(listSub,countDownLatch);
            //asyncService.batchUpdatePrdByParams(listSub);
            count++;
            logger.error("程序执行次数：{}",count);
        }
        try {
            countDownLatch.await(); //保证之前的所有的线程都执行完成，才会走下面的；
            // 这样就可以在下面拿到所有线程执行完的集合结果
        } catch (Exception e) {
            logger.error("阻塞异常:"+e.getMessage());
        }
        Date endTime = new Date();
        Long executeTime = endTime.getTime()-beginTime.getTime();
        rs.put("size",asyncDataList.size());
        rs.put("time",executeTime+"ms");

        return R.ok().data(rs);
    }

    private static List<String> collectLocalDates(LocalDate start, LocalDate end){
        return Stream.iterate(start, localDate -> localDate.plusDays(1))
                //截断无限流，长度为起始时间和结束时间的差+1个
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                //由于最后要的是字符串，所以map转换一下
                .map(LocalDate::toString)
                //把流收集为List
                .collect(Collectors.toList());
    }

    /**
     * 分割List
     */
    public <T> List splitList(List<T> list,int size) {
        List<List<T>> lists = new ArrayList<>();
        List<List<T>> partitions = Lists.partition(list, size);
        for (List<T> ls : partitions) {
            lists.add(ls);
        }
        return lists;
    }

    public List<AsyncData> getSyncData(List<String> dateList){
        //组装数据
        List<AsyncData> asyncDataList = new ArrayList<>();
        for (int i = 0; i < dateList.size(); i++) {
            AsyncData asyncData = new AsyncData();
            asyncData.setName("张三"+i);
            asyncData.setContent("描述信息："+i);
            asyncData.setSyncDate(dateList.get(i));
            asyncData.setCreateTime(new Date());
            asyncDataList.add(asyncData);
        }
        return asyncDataList;
    }

    @GetMapping(path = "getEarthquakeReport")
    @ResponseBody
    public R getEarthquakeReport(){
        List<Map> earthquakeReport = asyncService.getEarthquakeReport();
        return R.ok().data(earthquakeReport);
    }

}
